package logger

import (
	"context"
	"fmt"
	"github.com/google/wire"
	"sieve_admin_server_userpass/app/dao"
	logDao "sieve_admin_server_userpass/app/dao/logger"
	"sieve_admin_server_userpass/app/dao/user"
	"sieve_admin_server_userpass/app/schema"
	schemaLog "sieve_admin_server_userpass/app/schema/logger"
	serviceSys "sieve_admin_server_userpass/app/service/sys"
	"sieve_admin_server_userpass/lib/log"
	"sieve_admin_server_userpass/pkg/util"
	"strings"
	"time"
)

var (
	BusinessSet = wire.NewSet(wire.Struct(new(BusinessSrv), "*"))
)

type BusinessSrv struct {
	UserRepo           *dao.UserRepo
	RoleSrv            *serviceSys.RoleSrv
	BusinessRecordRepo *dao.BusinessRecordRepo
}

func (a *BusinessSrv) QueryLogName(ctx context.Context, reqArgs map[string]interface{}, p schema.PaginationParam, repKeys []string) interface{} {

	req, err := a.BusinessRecordRepo.Query(ctx, reqArgs, p, repKeys)
	if err != nil {
		return err
	}
	return req
}

func (a *BusinessSrv) Query(ctx context.Context, uid, roleId uint64, reqArgs map[string]interface{}, p schema.PaginationParam) interface{} {

	var (
		creatorNameLike      string
		creatorRoleNameLike  string
		creatorRoleAliasLike string
	)

	if _, ok := reqArgs["creator_name"]; ok {
		creatorNameLike = "AND user.account = '" + reqArgs["creator_name"].(string) + "'"
		delete(reqArgs, "creator_name")
	}

	if _, ok := reqArgs["creator_role_name"]; ok {
		creatorRoleNameLike = "AND role.name = '" + reqArgs["creator_role_name"].(string) + "'"
		delete(reqArgs, "creator_role_name")
	}

	if _, ok := reqArgs["creator_role_alias"]; ok {
		creatorRoleAliasLike = "AND role.alias = '" + reqArgs["creator_role_alias"].(string) + "'"
		delete(reqArgs, "creator_role_alias")
	}

	if _, ok := reqArgs["creator_name_like"]; ok {
		creatorNameLike = "AND user.account LIKE " + "'%" + reqArgs["creator_name_like"].(string) + "%'"
		delete(reqArgs, "creator_name_like")
	}

	if _, ok := reqArgs["creator_role_name_like"]; ok {
		creatorRoleNameLike = "AND role.name LIKE " + "'%" + reqArgs["creator_role_name_like"].(string) + "%'"
		delete(reqArgs, "creator_role_name_like")
	}

	if _, ok := reqArgs["creator_role_alias_like"]; ok {
		creatorRoleAliasLike = "AND role.alias LIKE " + "'%" + reqArgs["creator_role_alias_like"].(string) + "%'"
		delete(reqArgs, "creator_role_alias_like")
	}

	var leaderCondition string
	if a.RoleSrv.IsSalespersonRole(roleId) {
		leaderCondition = fmt.Sprintf(" AND (user.id = %v OR user.leader_id = %v OR user.top_leader_id = %v)", uid, uid, uid)
	}

	var (
		columnType = schemaLog.QueryBusinessLogRsp{}
		joinString = []string{
			fmt.Sprintf(`INNER JOIN user ON user.id = business_record.creator AND user.deleted = 0 %v %v`, creatorNameLike, leaderCondition),
			fmt.Sprintf(`INNER JOIN role ON role.id = user.role_id AND role.deleted = 0 %v %v`, creatorRoleNameLike, creatorRoleAliasLike),
		}

		repKeys = append(util.Struct2Slice(logDao.BusinessRecord{}, "json", "business_record"), []string{
			"user.account as creator_name",
			"role.id as creator_role_id",
			"role.name as creator_role_name",
			"role.alias as creator_role_alias",
		}...)
	)

	ctx = context.WithValue(
		context.WithValue(ctx, "join", strings.Join(joinString, " ")),
		"column_types", columnType,
	)

	req, err := a.BusinessRecordRepo.Query(ctx, reqArgs, p, repKeys)
	if err != nil {
		return err
	}
	return req
}

func (a *BusinessSrv) Create(ctx context.Context, userId uint64, item map[string]interface{}) interface{} {

	var (
		now = time.Now().Unix()
		def = map[string]interface{}{
			"creator":    userId,
			"create_at":  now,
			"updated_at": now,
		}
	)

	for k, v := range def {
		item[k] = v
	}

	return a.BusinessRecordRepo.Create(ctx, item)
}

func (a *BusinessSrv) getUserInfo(ctx context.Context, id uint64) interface{} {

	var (
		querySQL = fmt.Sprintf(`
		SELECT * FROM user
		WHERE id = %v
`, id)
	)

	resp, err := a.UserRepo.QueryRaw(ctx, querySQL, user.User{})
	if err != nil {
		log.Err(fmt.Sprintf("load session err %+v", err))
		return err
	}

	var userInfo *user.User
	for _, v := range resp {
		userInfo = v.(*user.User)
		break
	}

	return userInfo
}

func (a *BusinessSrv) CreateBusinessRecord(ctx context.Context, userId uint64, logType, logName, logMsg string) interface{} {

	resp := a.getUserInfo(ctx, userId)
	if resp == nil {
		return nil
	}

	item := map[string]interface{}{
		"type": logType,
		"name": logName,
		"msg":  logMsg,
		// "login_account": userInfo.Account,
	}
	if userInfo, ok := resp.(*user.User); ok && userInfo != nil {
		item["login_account"] = userInfo.Account
	}

	return a.Create(ctx, userId, item)
}
